package com.mar.meclient.bt.impl;

import java.io.IOException;

import javax.bluetooth.L2CAPConnection;
import javax.bluetooth.L2CAPConnectionNotifier;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.Connector;

import net.java.dev.marge.communication.CommunicationChannel;
import net.java.dev.marge.communication.ConnectionListener;
import net.java.dev.marge.communication.L2CAPCommunicationChannel;
import net.java.dev.marge.entity.ClientDevice;
import net.java.dev.marge.entity.ServerDevice;
import net.java.dev.marge.entity.config.ClientConfiguration;
import net.java.dev.marge.entity.config.ServerConfiguration;
import net.java.dev.marge.factory.CommunicationFactory;

/**
 * Create Client and Server Devices using the Bluetooth L2CAP Protocol.
 * TODO: used as example here/ purpose is to specify l2cap MTU values
 * @deprecated
 */
class CustomL2CAPCommunicationFactory implements CommunicationFactory {
	
	private static final String PROTOCOL_NAME = "btl2cap";

	/**
	 * Creates a <code>ClientDevice</code> under the given configurations. The
	 * Client will connect to the server using the L2CAP Protocol.
	 * 
	 * @param configuration
	 *            <code>ClientConfiguration</code> used to create the client.
	 * @return Created <code>ClientDevice</code>.
	 * @throws IOException
	 *             if an I/O error occurs.
	 */
	public ClientDevice connectToServer(ClientConfiguration configuration)
			throws IOException {

		ClientDeviceFactory clientFactory = new ClientDeviceFactory(configuration);
		clientFactory.start();

		synchronized (this) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		if (clientFactory.getException() != null) {
			throw clientFactory.getException();
		}

		return clientFactory.getDevice();
	}

	/**
	 * Creates a <code>ServerDevice</code> with the given configurations. The
	 * ServerDevice instance will be given to the <code>ConnetionListener</code>
	 * when the connection is estabilished and it will use the L2CAP Protocol.
	 * 
	 * @param configuration
	 *            <code>ServerConfiguration</code> used to create the server.
	 * @param listener
	 *            Listener that will be notified when a connection is
	 *            estabilished.
	 */
	public void waitClients(final ServerConfiguration configuration,
			final ConnectionListener listener) {
		new Thread() {
			public void run() {
				try {
					//CustomL2CAPCommunicationFactory.super.setDiscoverableStatus();
					configuration.setProtocol(PROTOCOL_NAME);
					L2CAPConnectionNotifier conn = (L2CAPConnectionNotifier) Connector.open(configuration.getConnectionURL());
					//CustomL2CAPCommunicationFactory.super.updateRecord(conn, configuration.getUuid());
                    //listener.initialisationSucessful();
					L2CAPConnection connection = conn.acceptAndOpen();
					CommunicationChannel channel = new L2CAPCommunicationChannel(connection);
					RemoteDevice remoteDevice = RemoteDevice.getRemoteDevice(channel.getConnection());
					ServerDevice serverDevice = new ServerDevice(configuration.getCommunicationListener(), channel, configuration.getReadInterval());
					listener.connectionEstablished(serverDevice, remoteDevice);
					//CustomL2CAPCommunicationFactory.super.increaseNumberOfConnections();
					int connections = 0;
					while (connections < configuration.getMaxNumberOfConnections()) {
						connection = conn.acceptAndOpen();
						channel = new L2CAPCommunicationChannel(connection);
						remoteDevice = RemoteDevice.getRemoteDevice(channel.getConnection());
						serverDevice.addChannel(channel);
						listener.connectionEstablished(serverDevice,remoteDevice);
						connections++;
					}

				} catch (IOException e) {
					e.printStackTrace();
					listener.errorOnConnection(e);
				}
			}
		}.start();
	}

	final public class ClientDeviceFactory extends Thread {

		private IOException exception;

		private ClientConfiguration configuration;

		private ClientDevice device;

		public ClientDeviceFactory(ClientConfiguration configuration) {
			this.configuration = configuration;
			this.exception = null;
		}

		public void run() {
			try {
				//TODO: customize connection url:
				String connectionURL = configuration.getConnectionURL();
				connectionURL += ";receiveMTU=700";
				connectionURL += ";transmitMTU=512";
				CommunicationChannel channel = new L2CAPCommunicationChannel((L2CAPConnection) Connector.open(connectionURL));
				device = new ClientDevice(configuration.getCommunicationListener(), channel, configuration.getReadInterval());
			} catch (IOException e) {
				exception = e;
			}
			synchronized (CustomL2CAPCommunicationFactory.this) {
				CustomL2CAPCommunicationFactory.this.notify();
			}
		}

		public ClientDevice getDevice() {
			return device;
		}

		public IOException getException() {
			return exception;
		}
	}
}

